/**
 * Copyright (c) 2013-2022 Nikita Koksharov
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.redisson.api;

import java.time.Duration;
import java.util.concurrent.TimeUnit;

/**
 * 提供批处理操作的配置选项的最终类。
 * 该类封装了批处理操作的各种选项，如并发度、超时设置等，
 * 为批处理提供了一种配置方式。
 */
public final class BatchOptions {

    /**
     * 执行模式枚举，定义了操作数据的不同方式和策略。
     * 这些模式决定了数据操作的原子性、存储位置和性能特点。
     */
    public enum ExecutionMode {
        /**
         * 在Redis中以原子方式读取数据。
         * 这种模式利用Redis的事务特性来保证读操作的原子性。
         */
        REDIS_READ_ATOMIC,

        /**
         * 在Redis中以原子方式写入数据。
         * 这种模式利用Redis的事务特性来保证写操作的原子性。
         */
        REDIS_WRITE_ATOMIC,

        /**
         * 在内存中处理数据。
         * 这种模式下的操作快速但不持久化，适用于对数据持久化要求不高的场景。
         */
        IN_MEMORY,

        /**
         * 在内存中以原子方式处理数据。
         * 这种模式提供了最高的操作原子性和性能，但同样不保证数据的持久化。
         */
        IN_MEMORY_ATOMIC
    }

    
    private ExecutionMode executionMode = ExecutionMode.IN_MEMORY;
    
    /**
     * 设置响应超时时间，单位为毫秒。此超时时间用于等待操作的完成。
     */
    private long responseTimeout;

    /**
     * 设置重试尝试的次数。初始值设置为-1，表示使用默认的重试策略。
     */
    private int retryAttempts = -1;

    /**
     * 设置重试尝试之间的间隔时间，单位为毫秒。这用于在失败后等待一段时间再进行重试。
     */
    private long retryInterval;

    /**
     * 设置同步操作的超时时间，单位为毫秒。这用于确保同步操作在指定时间内完成。
     */
    private long syncTimeout;

    /**
     * 设置需要同步的从服务器数量。这用于主从复制的场景，确保数据的高可用性。
     */
    private int syncSlaves;

    /**
     * 设置需要同步的本地服务器数量。这用于集群内部的同步，确保数据的一致性。
     */
    private int syncLocals;

    /**
     * 标志是否启用AOF（Append-Only File）同步。当设置为true时，数据将通过AOF文件进行同步。
     */
    private boolean syncAOF;

    /**
     * 标志是否跳过操作结果。当设置为true时，操作完成后不会返回结果。
     */
    private boolean skipResult;


    /**
     * 构造
     */
    private BatchOptions() {
    }

    public static BatchOptions defaults() {
        return new BatchOptions();
    }
    public BatchOptions responseTimeout(long timeout, TimeUnit unit) {
        this.responseTimeout = unit.toMillis(timeout);
        return this;
    }
    public BatchOptions retryAttempts(int retryAttempts) {
        this.retryAttempts = retryAttempts;
        return this;
    }
    public BatchOptions retryInterval(long retryInterval, TimeUnit retryIntervalUnit) {
        this.retryInterval = retryIntervalUnit.toMillis(retryInterval);
        return this;
    }
    public BatchOptions sync(int slaves, Duration timeout) {
        this.syncSlaves = slaves;
        this.syncTimeout = timeout.toMillis();
        return this;
    }
    public BatchOptions skipResult() {
        skipResult = true;
        return this;
    }
    public BatchOptions syncAOF(int localNum, int slaves, Duration timeout) {
        this.syncSlaves = slaves;
        this.syncAOF = true;
        this.syncLocals = localNum;
        this.syncTimeout = timeout.toMillis();
        return this;
    }
    public BatchOptions executionMode(ExecutionMode executionMode) {
        this.executionMode = executionMode;
        return this;
    }


    public long getResponseTimeout() {
        return responseTimeout;
    }
    public int getRetryAttempts() {
        return retryAttempts;
    }
    public long getRetryInterval() {
        return retryInterval;
    }

    public long getSyncTimeout() {
        return syncTimeout;
    }
    public int getSyncSlaves() {
        return syncSlaves;
    }
    public boolean isSkipResult() {
        return skipResult;
    }
    public int getSyncLocals() {
        return syncLocals;
    }
    public boolean isSyncAOF() {
        return syncAOF;
    }
    public ExecutionMode getExecutionMode() {
        return executionMode;
    }

    @Override
    public String toString() {
        return "BatchOptions [queueStore=" + executionMode + "]";
    }

    @Deprecated
    public BatchOptions syncSlaves(int slaves, long timeout, TimeUnit unit) {
        this.syncSlaves = slaves;
        this.syncTimeout = unit.toMillis(timeout);
        return this;
    }
}
